`ifndef {{NAME}}_DRIVER__SV
`define {{NAME}}_DRIVER__SV

class {{name}}_driver extends uvm_driver#({{name}}_transaction);

    virtual {{name}}_if vif;

    // 使用宏函数uvm_component_utils注册driver类，可以使用run_test函数通过类名字符串实例化并调用main_phase
    `uvm_component_utils({{name}}_driver);

    function new(string name = "{{name}}_driver", uvm_component parent = null);
        super.new(name, parent);
        `uvm_info("{{name}}_driver", "new is called", UVM_LOW);
    endfunction

    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        `uvm_info("{{name}}_driver", "build_phase is called", UVM_LOW);
        if (!uvm_config_db#(virtual {{name}}_if)::get(this, "", "vif", vif))
            `uvm_fatal("{{name}}_driver", "virtual interface must be set for vif!");
    endfunction
    
    extern virtual task main_phase(uvm_phase phase);
    extern virtual task drive_one_pkt({{name}}_transaction tr);

endclass

task {{name}}_driver::main_phase(uvm_phase phase);
    `uvm_info("{{name}}_driver", "main_phase is called", UVM_LOW);
    
    vif.data <= 8'b0;
    vif.valid <= 1'b0;

    while(!vif.rst_n)
        @(posedge vif.clk);
    
    while (1) begin
        seq_item_port.get_next_item(req);
        drive_one_pkt(req);
        seq_item_port.item_done();
    end

    repeat(5) @(posedge vif.clk);

    $display("the full name of current component is: %s", get_full_name());
endtask

task {{name}}_driver::drive_one_pkt({{name}}_transaction tr);
    byte unsigned data_q[];
    int data_size;

    data_size = tr.pack_bytes(data_q) / 8;

   `uvm_info("{{name}}_driver", "begin to drive one pkt", UVM_LOW);
   repeat(3) @(posedge vif.clk);
   
   for (int i = 0; i < data_size; i++) begin
       @(posedge vif.clk);
       vif.valid <= 1'b1;
       vif.data <= data_q[i];
   end

   @(posedge vif.clk);
   vif.valid <= 1'b0;
   `uvm_info("{{name}}_driver", "end drive one pkt, print it:", UVM_LOW);
   tr.print();
endtask

`endif